﻿using System;
using System.Collections.Generic;
using System.Data.Linq.SqlClient;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;

namespace PropertyExpression.TypedSqlBuilder.Test
{
    public static class DataClassesExtensions
    {
        public static IEnumerable<TResult> ExecuteQuery<TResult>(
            this DataClassesDataContext it,
            string query,
            Action<Action<string, object>> parameterActionExecuter)
        {
            throw new NotImplementedException();
        }
    }

    public class ProductProjection
    {
        public string ProductNumber { get; set; }
        public string Name { get; set; }
    }

    [TestFixture]
    public class LinqTest
    {
        [Test]
        public void Test2()
        {
            using (var context = new DataClassesDataContext())
            {
                IEnumerable<ProductProjection> productProjections = GetProducts(context, "ProductNumber111", "Name222");
            }
        }

        private static IEnumerable<ProductProjection> GetProducts(
            DataClassesDataContext context, string productNumber, string name)
        {
            return context.ExecuteQuery<ProductProjection>(
@"SELECT TOP 10 
    ProductNumber, 
    Name 
FROM 
    Production.Product 
WHERE 
    ProductNumber = @ProductNumber
    OR
    Name = @Name
",
                parameterAdder =>
                    {
                        parameterAdder("@ProductNumber", productNumber);
                        parameterAdder("@Name", name);
                    }
                );
        }

        [Test]
        public void Test()
        {
            using (var context = new DataClassesDataContext())
            {
                LinqTestQuery(context);
                LinqTestQuery(context);

                var watch = new Stopwatch();
                watch.Start();

                for (var i = 0; i < 100; i++)
                {
                    LinqTestQuery(context);
                }

                Console.WriteLine(watch.ElapsedMilliseconds);
            }
        }

        private static void LinqTestQuery(DataClassesDataContext context)
        {
            LinqTestQuery(context, "Mountain%", "P%", new DateTime(2003, 1, 1), new DateTime(2004, 7, 7));
        }

        private static void LinqTestQuery(DataClassesDataContext context, string productName, string contactFromGroupFirstName, DateTime startDateTime, DateTime endDateTime)
        {
            var queryable =
                from salesOrderHeader in context.SalesOrderHeaders
                join salesOrderDetail in context.SalesOrderDetails
                    on salesOrderHeader.SalesOrderID equals salesOrderDetail.SalesOrderID
                join specialOfferProduct in context.SpecialOfferProducts
                    on new {salesOrderDetail.SpecialOfferID, salesOrderDetail.ProductID}
                    equals new {specialOfferProduct.SpecialOfferID, specialOfferProduct.ProductID}
                join specialOffer in context.SpecialOffers
                    on specialOfferProduct.SpecialOfferID equals specialOffer.SpecialOfferID
                join product in context.Products
                    on specialOfferProduct.ProductID equals product.ProductID
                join individual in context.Individuals
                    on salesOrderHeader.CustomerID equals individual.CustomerID
                    into individualGroup
                from individualFromGroup in individualGroup.DefaultIfEmpty()
                join contact in context.Contacts
                    on individualFromGroup.ContactID equals contact.ContactID
                    into contactGroup
                from contactFromGroup in contactGroup.DefaultIfEmpty()
                where
                    SqlMethods.Like(product.Name, productName)
                    &&
                    SqlMethods.Like(contactFromGroup.FirstName, contactFromGroupFirstName)
                    &&
                    salesOrderHeader.OrderDate >= startDateTime
                    &&
                    salesOrderHeader.OrderDate <= endDateTime
                select new
                           {
                               contactFromGroup.FirstName,
                               contactFromGroup.LastName,
                               product.Name,
                               salesOrderDetail.OrderQty,
                               salesOrderDetail.UnitPrice,
                               specialOffer.Category,
                               salesOrderHeader.OrderDate
                           };

            queryable.ToList();
        }
    }
}
